import { computed } from 'vue'
import { dayjs } from '../common/dayjs'
import { isArray, isFunction, padZero } from '../common/util'
import { useTranslate } from '../composables/useTranslate'
import type {
    CalendarDayType,
    CalendarItem,
    CalendarTimeFilter,
    CalendarType,
} from './types'
const { translate } = useTranslate('calendar-view')

const weeks = computed(() => {
    return [
        translate('weeks.sun'),
        translate('weeks.mon'),
        translate('weeks.tue'),
        translate('weeks.wed'),
        translate('weeks.thu'),
        translate('weeks.fri'),
        translate('weeks.sat'),
    ]
})

/**
 * 比较两个时间的日期是否相等
 * @param {timestamp} date1
 * @param {timestamp} date2
 */
export function compareDate(date1: number, date2: number | null) {
    const dateValue1 = new Date(date1)
    const dateValue2 = new Date(date2 || '')

    const year1 = dateValue1.getFullYear()
    const year2 = dateValue2.getFullYear()
    const month1 = dateValue1.getMonth()
    const month2 = dateValue2.getMonth()
    const day1 = dateValue1.getDate()
    const day2 = dateValue2.getDate()

    if (year1 === year2) {
        if (month1 === month2) {
            return day1 === day2 ? 0 : day1 > day2 ? 1 : -1
        }
        return month1 === month2 ? 0 : month1 > month2 ? 1 : -1
    }

    return year1 > year2 ? 1 : -1
}

/**
 * 判断是否是范围选择
 * @param {string} type
 */
export function isRange(type: CalendarType) {
    return type.indexOf('range') > -1
}

/**
 * 比较两个日期的月份是否相等
 * @param {timestamp} date1
 * @param {timestamp} date2
 */
export function compareMonth(date1: number, date2: number) {
    const dateValue1 = new Date(date1)
    const dateValue2 = new Date(date2)

    const year1 = dateValue1.getFullYear()
    const year2 = dateValue2.getFullYear()
    const month1 = dateValue1.getMonth()
    const month2 = dateValue2.getMonth()

    if (year1 === year2) {
        return month1 === month2 ? 0 : month1 > month2 ? 1 : -1
    }

    return year1 > year2 ? 1 : -1
}

/**
 * 比较两个日期的年份是否一致
 * @param {timestamp} date1
 * @param {timestamp} date2
 */
export function compareYear(date1: number, date2: number) {
    const dateValue1 = new Date(date1)
    const dateValue2 = new Date(date2)

    const year1 = dateValue1.getFullYear()
    const year2 = dateValue2.getFullYear()

    return year1 === year2 ? 0 : year1 > year2 ? 1 : -1
}

/**
 * 获取一个月的最后一天
 * @param {number} year
 * @param {number} month
 */
export function getMonthEndDay(year: number, month: number) {
    return 32 - new Date(year, month - 1, 32).getDate()
}

/**
 * 格式化年月
 * @param {timestamp} date
 */
export function formatMonthTitle(date: number) {
    return dayjs(date).format(translate('monthTitle'))
}

/**
 * 根据下标获取星期
 * @param {number} index
 */
export function getWeekLabel(index: number) {
    if (index >= 7) {
        index = index % 7
    }

    return weeks.value[index]
}

/**
 * 格式化年份
 * @param {timestamp} date
 */
export function formatYearTitle(date: number) {
    return dayjs(date).format(translate('yearTitle'))
}

/**
 * 根据最小日期和最大日期获取这之间总共有几个月份
 * @param {timestamp} minDate
 * @param {timestamp} maxDate
 */
export function getMonths(minDate: number, maxDate: number) {
    const months: number[] = []
    const month = new Date(minDate)
    month.setDate(1)

    while (compareMonth(month.getTime(), maxDate) < 1) {
        months.push(month.getTime())
        month.setMonth(month.getMonth() + 1)
    }

    return months
}

/**
 * 根据最小日期和最大日期获取这之间总共有几年
 * @param {timestamp} minDate
 * @param {timestamp} maxDate
 */
export function getYears(minDate: number, maxDate: number) {
    const years: number[] = []
    const year = new Date(minDate)
    year.setMonth(0)
    year.setDate(1)

    while (compareYear(year.getTime(), maxDate) < 1) {
        years.push(year.getTime())
        year.setFullYear(year.getFullYear() + 1)
    }

    return years
}

/**
 * 获取一个日期所在周的第一天和最后一天
 * @param {timestamp} date
 */
export function getWeekRange(date: number, firstDayOfWeek: number) {
    if (firstDayOfWeek >= 7) {
        firstDayOfWeek = firstDayOfWeek % 7
    }

    const dateValue = new Date(date)
    dateValue.setHours(0, 0, 0, 0)
    const year = dateValue.getFullYear()
    const month = dateValue.getMonth()
    const day = dateValue.getDate()
    const week = dateValue.getDay()

    const weekStart = new Date(
        year,
        month,
        day - ((7 + week - firstDayOfWeek) % 7),
    )
    const weekEnd = new Date(
        year,
        month,
        day + 6 - ((7 + week - firstDayOfWeek) % 7),
    )

    return [weekStart.getTime(), weekEnd.getTime()]
}

/**
 * 获取日期偏移量
 * @param {timestamp} date1
 * @param {timestamp} date2
 */
export function getDayOffset(date1: number, date2: number) {
    return (date1 - date2) / (24 * 60 * 60 * 1000) + 1
}

/**
 * 获取偏移日期
 * @param {timestamp} date
 * @param {number} offset
 */
export function getDayByOffset(date: number, offset: number) {
    const dateValue = new Date(date)
    dateValue.setDate(dateValue.getDate() + offset)

    return dateValue.getTime()
}

export const getPrevDay = (date: number) => getDayByOffset(date, -1)
export const getNextDay = (date: number) => getDayByOffset(date, 1)

/**
 * 获取月份偏移量
 * @param {timestamp} date1
 * @param {timestamp} date2
 */
export function getMonthOffset(date1: number, date2: number) {
    const dateValue1 = new Date(date1)
    const dateValue2 = new Date(date2)

    const year1 = dateValue1.getFullYear()
    const year2 = dateValue2.getFullYear()
    let month1 = dateValue1.getMonth()
    const month2 = dateValue2.getMonth()

    month1 = (year1 - year2) * 12 + month1

    return month1 - month2 + 1
}

/**
 * 获取偏移月份
 * @param {timestamp} date
 * @param {number} offset
 */
export function getMonthByOffset(date: number, offset: number) {
    const dateValue = new Date(date)
    dateValue.setMonth(dateValue.getMonth() + offset)

    return dateValue.getTime()
}

/**
 * 获取默认时间，格式化为数组
 * @param {array|string|null} defaultTime
 */
export function getDefaultTime(defaultTime: string[] | string | null) {
    if (isArray(defaultTime)) {
        const startTime = (defaultTime[0] || '00:00:00')
            .split(':')
            .map((item: string) => {
                return parseInt(item)
            })
        const endTime = (defaultTime[1] || '00:00:00')
            .split(':')
            .map((item) => {
                return parseInt(item)
            })
        return [startTime, endTime]
    } else {
        const time = (defaultTime || '00:00:00').split(':').map((item) => {
            return parseInt(item)
        })

        return [time, time]
    }
}

/**
 * 根据默认时间获取日期
 * @param {timestamp} date
 * @param {array} defaultTime
 */
export function getDateByDefaultTime(date: number, defaultTime: number[]) {
    const dateValue = new Date(date)
    dateValue.setHours(defaultTime[0])
    dateValue.setMinutes(defaultTime[1])
    dateValue.setSeconds(defaultTime[2])

    return dateValue.getTime()
}

/**
 * 获取经过 iteratee 格式化后的长度为 n 的数组
 * @param {number} n
 * @param {function} iteratee
 */
const times = (n: number, iteratee: (index: number) => CalendarItem) => {
    let index: number = -1
    const result: CalendarItem[] = Array(n < 0 ? 0 : n)
    while (++index < n) {
        result[index] = iteratee(index)
    }
    return result
}

/**
 * 获取时分秒
 * @param {timestamp}} date
 */
const getTime = (date: number) => {
    const dateValue = new Date(date)
    return [
        dateValue.getHours(),
        dateValue.getMinutes(),
        dateValue.getSeconds(),
    ]
}

/**
 * 根据最小最大日期获取时间数据，用于填入picker
 * @param {*} param0
 */
export function getTimeData({
    date,
    minDate,
    maxDate,
    isHideSecond,
    filter,
}: {
    date: number
    minDate: number
    maxDate: number
    isHideSecond: boolean
    filter?: CalendarTimeFilter
}) {
    const compareMin = compareDate(date, minDate)
    const compareMax = compareDate(date, maxDate)

    let minHour = 0
    let maxHour = 23
    let minMinute = 0
    let maxMinute = 59
    let minSecond = 0
    let maxSecond = 59

    if (compareMin === 0) {
        const minTime = getTime(minDate)
        const currentTime = getTime(date)

        minHour = minTime[0]
        if (minTime[0] === currentTime[0]) {
            minMinute = minTime[1]

            if (minTime[1] === currentTime[1]) {
                minSecond = minTime[2]
            }
        }
    }

    if (compareMax === 0) {
        const maxTime = getTime(maxDate)
        const currentTime = getTime(date)

        maxHour = maxTime[0]
        if (maxTime[0] === currentTime[0]) {
            maxMinute = maxTime[1]

            if (maxTime[1] === currentTime[1]) {
                maxSecond = maxTime[2]
            }
        }
    }

    let columns: CalendarItem[][] = []
    let hours = times(24, (index) => {
        return {
            label: translate('hour', padZero(index)),
            value: index,
            disabled: index < minHour || index > maxHour,
        }
    })
    let minutes = times(60, (index) => {
        return {
            label: translate('minute', padZero(index)),
            value: index,
            disabled: index < minMinute || index > maxMinute,
        }
    })
    let seconds: CalendarItem[] = []
    if (filter && isFunction(filter)) {
        hours = filter({
            type: 'hour',
            values: hours,
        })
        minutes = filter({
            type: 'minute',
            values: minutes,
        })
    }

    if (!isHideSecond) {
        seconds = times(60, (index) => {
            return {
                label: translate('second', padZero(index)),
                value: index,
                disabled: index < minSecond || index > maxSecond,
            }
        })
        if (filter && isFunction(filter)) {
            seconds = filter({
                type: 'second',
                values: seconds,
            })
        }
    }

    columns = isHideSecond ? [hours, minutes] : [hours, minutes, seconds]

    return columns
}

/**
 * 获取当前是第几周
 * @param {timestamp} date
 */
export function getWeekNumber(date: number | Date) {
    date = new Date(date)
    date.setHours(0, 0, 0, 0)
    // Thursday in current week decides the year.
    date.setDate(date.getDate() + 3 - ((date.getDay() + 6) % 7))
    // January 4 is always in week 1.
    const week = new Date(date.getFullYear(), 0, 4)
    // Adjust to Thursday in week 1 and count number of weeks from date to week 1.
    // Rounding should be fine for Daylight Saving Time. Its shift should never be more than 12 hours.
    return (
        1 +
        Math.round(
            ((date.getTime() - week.getTime()) / 86400000 -
                3 +
                ((week.getDay() + 6) % 7)) /
                7,
        )
    )
}

export function getItemClass(
    monthType: CalendarDayType,
    value: number | null | (number | null)[],
    type: CalendarType,
) {
    const classList = ['is-' + monthType]

    if (type.indexOf('range') > -1 && isArray(value)) {
        if (!value || !value[1]) {
            classList.push('is-without-end')
        }
    }

    return classList.join(' ')
}
